package com.agent.auth.service;

import cn.hutool.core.bean.BeanUtil;
import com.agent.auth.entity.UserSession;
import com.agent.auth.mapper.UserSessionMapper;
import com.agent.common.entity.TokenPair;
import com.agent.common.entity.UserContext;
import com.agent.common.exception.AuthenticationException;
import com.agent.common.result.ApiResponse;
import com.agent.common.result.ResultCode;
import com.agent.common.utils.IdGenerator;
import com.agent.common.utils.JwtUtils;
import com.agent.user.api.feign.UserFeignClient;
import com.agent.user.api.resp.UserResp;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;

/**
 * 认证服务实现
 * @author Jeff_Wan
 * @description 处理用户认证核心逻辑
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AuthService {
    private final UserFeignClient userFeignClient;
    private final UserSessionMapper userSessionMapper;
    private final PasswordEncoder passwordEncoder;
    private final JwtUtils jwtUtils;

    /**
     * 邮箱登录
     * @param email 邮箱
     * @param password 密码
     * @return JWT令牌
     */
    public TokenPair loginWithEmail(String email, String password) {
        ApiResponse<UserResp> user = userFeignClient.getUserByEmail(email);
        if (!ApiResponse.isSuccess(user) || user.getData() == null) {
            throw new AuthenticationException(ResultCode.USER_NOT_EXIST);
        }

        if (!passwordEncoder.matches(password, user.getData().getPassword())) {
            throw new AuthenticationException(ResultCode.INVALID_CREDENTIALS);
        }

        return createUserSession(BeanUtil.copyProperties(user.getData(), UserContext.class));
    }

    /**
     * 创建用户会话
     * @param userContext 用户信息
     * @return 访问令牌
     */
    private TokenPair createUserSession(UserContext userContext) {
        // 生成令牌对
        TokenPair tokenPair = jwtUtils.generateTokenPair(userContext);

        // 创建会话记录
        UserSession session = new UserSession();
        session.setId(IdGenerator.getInstance().nextId());
        session.setUserId(userContext.getUserId());
        session.setSessionToken(tokenPair.getAccessToken());
        session.setRefreshToken(tokenPair.getRefreshToken());
        session.setExpiresAt(LocalDateTime.now().plus(30, ChronoUnit.MINUTES));
        session.setRefreshExpiresAt(LocalDateTime.now().plus(7, ChronoUnit.DAYS));
        session.setCreatedAt(LocalDateTime.now());
        session.setLastAccessedAt(LocalDateTime.now());
        session.setIsActive(true);
        userSessionMapper.insert(session);

        return tokenPair;
    }

    /**
     * 验证并提取用户上下文
     * @param token 访问令牌
     * @return 用户上下文
     */
    public UserContext validateAndExtractUserContext(String token) {
        if (!jwtUtils.validateRsaToken(token)) {
            throw new AuthenticationException(ResultCode.UNAUTHORIZED, "Invalid token");
        }

        return jwtUtils.extractUserContext(token, true);
    }

    /**
     * 获取用户上下文
     * @param userId 用户ID
     * @return 用户上下文
     */
    private UserContext getUserContext(Long userId) {
        ApiResponse<UserResp> user = userFeignClient.getUserById(userId);
        if (!ApiResponse.isSuccess(user) || user.getData() == null) {
            throw new AuthenticationException(ResultCode.USER_NOT_EXIST);
        }
        return BeanUtil.copyProperties(user.getData(), UserContext.class);
    }

    /**
     * 刷新访问令牌
     * @param refreshToken 刷新令牌
     * @return 新的令牌对
     */
    @Transactional
    public TokenPair renewAccessToken(String refreshToken) {
        // 验证刷新令牌有效性
        if (!jwtUtils.validateRsaToken(refreshToken)) {
            throw new AuthenticationException(ResultCode.UNAUTHORIZED, "Invalid refresh token");
        }

        // 获取会话记录
        UserSession session = userSessionMapper.findByRefreshToken(refreshToken);
        if (session == null || !session.getIsActive()) {
            throw new AuthenticationException(ResultCode.UNAUTHORIZED, "Session not found or inactive");
        }

        // 生成新的访问令牌
        Long userId = jwtUtils.extractClaim(refreshToken, true, "userId", Long.class);
        UserContext userContext = getUserContext(userId);
        String newAccessToken = jwtUtils.generateRsaToken(userContext);

        // 更新会话记录
        session.setSessionToken(newAccessToken);
        session.setExpiresAt(LocalDateTime.now().plus(30, ChronoUnit.MINUTES));
        session.setLastAccessedAt(LocalDateTime.now());
        userSessionMapper.updateById(session);

        return new TokenPair(newAccessToken, refreshToken);
    }

    /**
     * 退出登录
     * @param token 访问令牌
     */
    @Transactional
    public void logout(String token) {
        userSessionMapper.deactivateSession(token);
    }

    /**
     * 获取当前会话信息
     * @param accessToken 访问令牌
     * @return 会话信息
     */
    public UserSession getSessionByToken(String accessToken) {
        return userSessionMapper.findByToken(accessToken);
    }
}